<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2023/4/12
 * Time: 13:20
 */

namespace app\web\controller;

use app\api\controller\v2\Auth;
use app\common\cachemodel\FortuneNote;
use app\common\lib\util\Time;
use think\Controller;
use think\Exception;
use think\Log;

/**
 * 心情报告
 * Class NoteReport
 * @package app\web\controller
 */
class NoteReport extends Controller
{
    public function index()
    {
        $h = input('h/d', 0);
        $appType = $this->request->header('app-type', 'h5');
        //校验token
        try
        {
            $auth = new Auth();
            $auth->checkRequestAuth();
            $uid = $auth->user['id'];
        }
        catch (Exception $e)
        {
            //用户未登录、没有档案、校验失败的情况
            $uid = 0;
        }

        $data = $this->getMoodReportData($uid);

        $w = 2.7 * count($data['mood_chart']) - 1.31;

        return $this->fetch('note_report/index', [
            'h' => $h,
            'data' => $data,
            'w' => $w,
            'app_type' => $appType,
        ]);
    }

    /**
     * 获取心情笔记报告
     * @param int $uid
     * @return array
     * @throws \Exception
     */
    protected function getMoodReportData(int $uid)
    {
        $noteData = (new FortuneNote())->getNoteLists($uid, 2);
        $noteDataTmp = array_column($noteData, null, 'time');
        ksort($noteDataTmp);
        $nowDate = date('Ymd');
        $sevenTimes = Time::getNowTimeTimeRange($nowDate, '7');
        $thirtyTimes = Time::getNowTimeTimeRange($nowDate, '30');
        $ninetyTimes = array_merge(Time::getNowTimeTimeRange($nowDate, '90'), [strtotime(date('Ymd'))]);
        $moodConfig = config('mood');
        //心情分布变量初始化
        $sevenMoodList = [];
        $thirtyMoodList = [];
        $allMoodList = [];
        //心情占比变量初始化
        $sevenPercentTimes = [];
        $thirtyPercentTimes = [];
        $allPercentTimes = [];
        //心情持续时长变量初始化
        $positiveMaxDuration = $positiveTmpDuration = [];
        $positiveCurStart = null; // 当前连续区间的起始日期和结束日期
        $positiveTags = $positiveTmpTags = [];

        $negativeMaxDuration = $negativeTmpDuration = [];
        $negativeCurStart = null; // 当前连续区间的起始日期和结束日期
        $negativeTags = $negativeTmpTags = [];

        foreach ($noteDataTmp as $time => $datum)
        {
            $datum['mood_name'] = $moodConfig['mood_list'][$datum['mood']]['name'];
            $datum['mood_type'] = $moodConfig['mood_list'][$datum['mood']]['type'];
            $datum['mood_icon'] = $moodConfig['mood_list'][$datum['mood']]['icon'] . '.png';
            $datum['tags'] = [];
            foreach ($datum['tids'] as $tid)
            {
                $datum['tags'][] = [
                    'id' => $tid,
                    'name' => $moodConfig['tag_list'][$tid]['name']
                ];
            }
            //心情分布和占比
            $this->moodDistribution($sevenTimes, $time, $datum, $sevenMoodList, $sevenPercentTimes);
            $this->moodDistribution($thirtyTimes, $time, $datum, $thirtyMoodList, $thirtyPercentTimes);
            $this->moodDistribution($noteDataTmp, $time, $datum, $allMoodList, $allPercentTimes);
            if (in_array($datum['mood_type'], [4, 5], true))
            {
                $this->continueInfo($datum, $time, $positiveCurStart, $positiveTmpDuration, $positiveMaxDuration, $positiveTmpTags, $positiveTags);
            } elseif (in_array($datum['mood_type'], [1, 2], true))
            {
                $this->continueInfo($datum, $time, $negativeCurStart, $negativeTmpDuration, $negativeMaxDuration, $negativeTmpTags, $negativeTags);
            }
            $noteDataTmp[$time] = $datum;
        }

        //根据心情数量排序
        $this->sortMoodSum($sevenMoodList);
        $this->sortMoodSum($thirtyMoodList);
        $this->sortMoodSum($allMoodList);

        // 统计签到次数
        $this->totalMoodNum($sevenSum, $sevenMoodList);
        $this->totalMoodNum($thirtySum, $thirtyMoodList);
        $this->totalMoodNum($allSum, $allMoodList);

        //90天+当天的心情曲线
        $eightCanvas = [];
        sort($ninetyTimes);
        foreach ($ninetyTimes as $time)
        {
            $eightCanvas[] = [
                'day' => date('d', $time),
                'score' => $noteDataTmp[$time]['mood_type'] ?? 3
            ];
        }
        $resData = [
            //心情分布
            'mood_distribution' => [
                [
                    'tab_name' => '近7天',
                    'total' => $sevenSum ?? 0,
                    'most' => !empty($sevenMoodList) ? current($sevenMoodList)['name'] : '',
                    'mood_list' => $sevenMoodList ?? [],
                ], [
                    'tab_name' => '近30天',
                    'total' => $thirtySum ?? 0,
                    'most' => !empty($thirtyMoodList) ? current($thirtyMoodList)['name'] : '',
                    'mood_list' => $thirtyMoodList ?? [],
                ], [
                    'tab_name' => '全部',
                    'total' => $allSum ?? 0,
                    'most' => !empty($allMoodList) ? current($allMoodList)['name'] : '',
                    'mood_list' => $allMoodList ?? [],
                ]
            ],
            //心情曲线
            'mood_chart' => $eightCanvas,
            //心情占比
            'mood_distribution2' => [
                [
                    'tab_name' => '近7天',
                    'mood_status5' => isset($sevenPercentTimes[5]['count']) ? number_format($sevenPercentTimes[5]['count'] / $sevenSum, 2) * 100 : 0,
                    'mood_status4' => isset($sevenPercentTimes[4]['count']) ? number_format($sevenPercentTimes[4]['count'] / $sevenSum, 2) * 100 : 0,
                    'mood_status3' => isset($sevenPercentTimes[3]['count']) ? number_format($sevenPercentTimes[3]['count'] / $sevenSum, 2) * 100 : 0,
                    'mood_status2' => isset($sevenPercentTimes[2]['count']) ? number_format($sevenPercentTimes[2]['count'] / $sevenSum, 2) * 100 : 0,
                    'mood_status1' => isset($sevenPercentTimes[1]['count']) ? number_format($sevenPercentTimes[1]['count'] / $sevenSum, 2) * 100 : 0,
                ], [
                    'tab_name' => '近30天',
                    'mood_status5' => isset($thirtyPercentTimes[5]['count']) ? number_format($thirtyPercentTimes[5]['count'] / $thirtySum, 2) * 100 : 0,
                    'mood_status4' => isset($thirtyPercentTimes[4]['count']) ? number_format($thirtyPercentTimes[4]['count'] / $thirtySum, 2) * 100 : 0,
                    'mood_status3' => isset($thirtyPercentTimes[3]['count']) ? number_format($thirtyPercentTimes[3]['count'] / $thirtySum, 2) * 100 : 0,
                    'mood_status2' => isset($thirtyPercentTimes[2]['count']) ? number_format($thirtyPercentTimes[2]['count'] / $thirtySum, 2) * 100 : 0,
                    'mood_status1' => isset($thirtyPercentTimes[1]['count']) ? number_format($thirtyPercentTimes[1]['count'] / $thirtySum, 2) * 100 : 0,
                ],
                [
                    'tab_name' => '全部',
                    'mood_status5' => isset($allPercentTimes[5]['count']) ? number_format($allPercentTimes[5]['count'] / $allSum, 2) * 100 : 0,
                    'mood_status4' => isset($allPercentTimes[4]['count']) ? number_format($allPercentTimes[4]['count'] / $allSum, 2) * 100 : 0,
                    'mood_status3' => isset($allPercentTimes[3]['count']) ? number_format($allPercentTimes[3]['count'] / $allSum, 2) * 100 : 0,
                    'mood_status2' => isset($allPercentTimes[2]['count']) ? number_format($allPercentTimes[2]['count'] / $allSum, 2) * 100 : 0,
                    'mood_status1' => isset($allPercentTimes[1]['count']) ? number_format($allPercentTimes[1]['count'] / $allSum, 2) * 100 : 0,
                ]
            ],
        ];

        $positiveDiff = max(count($positiveTmpDuration), count($positiveMaxDuration));
        //正面标签
        if ($positiveDiff > 1)
        {
            // 处理最后一个时间段
            if (count($positiveTmpDuration) > count($positiveMaxDuration))
            {
                $positiveMaxDuration = $positiveTmpDuration;
                $positiveTags = $positiveTmpTags;
            }
            $longest_start = date('m.d', $positiveMaxDuration[0]); // 最长时间段的起始日期
            $longest_end = date('m.d', end($positiveMaxDuration)); // 最长时间段的结束日期
            $this->moodTags($positiveTags, $positiveTagsData);
            $resData['summarize_good'] = [
                'point_color' => '#00E99C',
                'bg_color' => '#F0FFFA',
                'tip' => "正面情绪持续最长时间：{$positiveDiff}天，在{$longest_start}-{$longest_end}，这段时间一定有很多让你开心的事情发生吧～ ",
                'day_num' => $positiveDiff,
                'tags' => isset($positiveTagsData) ? array_column($positiveTagsData, 'des') : [],
            ];
        }

        $negativeDiff = max(count($negativeTmpDuration), count($negativeTmpDuration));
        //负面标签
        if ($negativeDiff > 1)
        {
            // 处理最后一个时间段
            if (count($negativeTmpDuration) > count($negativeMaxDuration))
            {
                $negativeMaxDuration = $negativeTmpDuration;
                $negativeTags = $negativeTmpTags;
            }
            $longest_start = date('m.d', $negativeMaxDuration[0]); // 最长时间段的起始日期
            $longest_end = date('m.d', end($negativeMaxDuration)); // 最长时间段的结束日期
            $this->moodTags($negativeTags, $negativeTagsData);
            $resData['summarize_bad'] = [
                'point_color' => '#F5A623',
                'bg_color' => '#FFF9F5',
                'tip' => "负面情绪持续最长时间：{$negativeDiff}天，在{$longest_start}-{$longest_end}，这段时间一定有很多事情影响你的心情吧～ ",
                'day_num' => $negativeDiff,
                'tags' => isset($negativeTagsData) ? array_column($negativeTagsData, 'des') : [],
            ];
        }
        return $resData;
    }

    /**心情分布和占比结构组合
     * @return void
     */
    protected function moodDistribution($times, $time, $data, &$moodList, &$percentList)
    {
        if (isset($times[$time]))
        {
            //心情分布
            if (isset($moodList[$data['mood']]['num']))
            {
                $moodList[$data['mood']]['num']++;
                $moodList[$data['mood']]['name'] = $data['mood_name'] . ' x' . $moodList[$data['mood']]['num'];
            } else
            {
                $moodList[$data['mood']]['num'] = 1;
                $moodList[$data['mood']]['name'] = $data['mood_name'] . ' x1';
                $moodList[$data['mood']]['icon'] = $data['mood_icon'];
            }

            //心情占比
            if (array_key_exists($data['mood_type'], $percentList))
            {
                $percentList[$data['mood_type']]['count']++;
            } else
            {
                $percentList[$data['mood_type']]['count'] = 1;
            }
        }
    }

    /**
     * 心情数量排序
     * @param $moodList
     * @return void
     */
    protected function sortMoodSum(&$moodList)
    {
        $sortField = 'num';
        if (!empty($moodList))
        {
            $sortArray = array_column($moodList, $sortField);
            // 将需要排序的数据与原始数组关联（即保留原始数组键名）
            array_multisort($sortArray, SORT_DESC, $moodList);
        }
    }

    /**
     * 统计签到次数
     * @param $num
     * @param $moodList
     * @return void
     */
    protected function totalMoodNum(&$num, $moodList)
    {
        $sumField = 'num';

        if (!empty($moodList))
        {
            $sumArray = array_column($moodList, $sumField);
            // 使用 array_reduce() 函数对数据进行求和
            $num = array_reduce($sumArray, static function ($carry, $item)
            {
                return $carry + $item;
            });
        }
    }

    /**
     * 处理心情持续时间
     * @param $data
     * @param $time
     * @param $curStart
     * @param $tmpDuration
     * @param $maxDuration
     * @param $tmpTags
     * @param $tags
     * @return void
     */
    protected function continueInfo($data, $time, &$curStart, &$tmpDuration, &$maxDuration, &$tmpTags, &$tags)
    {
        $diff = $time - $curStart;
        if ($diff == 86400)
        {
            // 如果当前日期与前一个日期相差一天，则在当前时间段中添加该日期
            $tmpDuration[] = $time;
            $tmpTags = array_merge($tmpTags, $data['tags']);
        } else
        {
            // 否则，当前时间段结束，更新最长时间段
            if (count($tmpDuration) > count($maxDuration))
            {
                $maxDuration = $tmpDuration;
                $tags = $tmpTags;
            }
            $tmpDuration = [$time]; // 开始新的时间段
            $tmpTags = $data['tags'];
        }
        $curStart = $time;
    }

    /**
     * 心情标签
     * @param $moodTags
     * @param $resTags
     * @return void
     */
    protected function moodTags($moodTags, &$resTags)
    {
        // 使用 array_reduce() 函数对数据进行求和
        $resTags = array_reduce($moodTags, static function ($carry, $item)
        {
            $groupField = 'id';
            if (array_key_exists($item[$groupField], $carry))
            {
                $carry[$item[$groupField]]['count']++;
                $carry[$item[$groupField]]['des'] = $item['name'] . ' x' . $carry[$item[$groupField]]['count'];
            } else
            {
                $carry[$item[$groupField]]['count'] = 1;
                $carry[$item[$groupField]]['des'] = $item['name'] . ' x1';
            }
            return $carry;
        }, []);
    }

    /**
     * 心情排行
     * @throws Exception
     */
    public function ranking()
    {
        $h = input('h/d', 0);
        $appType = $this->request->header('app-type', 'h5');
        //校验token
        try
        {
            $auth = new Auth();
            $auth->checkRequestAuth();
            $rid = $auth->user['rid'];
        }
        catch (Exception $e)
        {
            //用户未登录、没有档案、校验失败的情况
            $rid = 0;
        }

        try
        {
            $appMoodNoteModel = new FortuneNote();
            //获取今日所有笔记
            $todayNote = $appMoodNoteModel->where(['time' => strtotime(date('Y-m-d')), 'tids' => ['neq', '']])->column('*', 'id');
            //笔记排行
            $todayTotalRankInfo = $appMoodNoteModel->getNoteRank($rid, $todayNote);

            //组合页面排行数据结构
            $this->rankData($todayTotalRankInfo['today_rank'], $todayRank);
            //获取近7天笔记
            $sevenRank = $appMoodNoteModel->getInRecentDays(1);
            //获取近30天笔记
            $thirtyRank = $appMoodNoteModel->getInRecentDays(2);

            $keys = array_keys($todayTotalRankInfo['today_rank']);
            $data = [
                'top' => [
                    'rank' => $todayTotalRankInfo['self_rank'] ?: '-',// 自己所属星座排名
                    'happy' => current($keys),// 最开心的星座
                    'sad' => empty($todayTotalRankInfo['today_rank'][12]) ? '-' : end($keys),// 最难过的星座
                    'my_sign' => $todayTotalRankInfo['self_sign'],// 自己所属的星座ID
                    'my_sign_count' => $todayTotalRankInfo['self_sign_user_num'],// 自己所属星座记录数量
                ],
                'rank_list' => [
                    // 今日排名
                    'today' => $todayRank,
                    // 最近7天排名（含今天）
                    'week' => $sevenRank,
                    // 最近30天排名（含今天）
                    'month' => $thirtyRank,
                ],
            ];
        }
        catch (\Exception $e)
        {
            Log::write('心情笔记排行 => ()异常：' . $e->getMessage() . '失败信息：' . $e->getFile() . ':' . $e->getLine() . ' - 档案ID:' . $rid, 'error', true);
            throw new Exception('服务异常,请稍后重试');
        }

        return $this->fetch('note_report/ranking', [
            'h' => $h,
            'data' => $data,
            'app_type' => $appType,
        ]);
    }

    /**
     * 组合页面排行数据结构
     * @param $data
     * @param $rank
     * @return void
     */
    protected function rankData($data, &$rank)
    {
        $tmp = [];
        foreach ($data as $sign => $score)
        {
            $tmp[] = [
                'sign_id' => $sign,
                'score' => $score
            ];
        }
        $rank = $tmp;
    }
}
